home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / DSHJ2 / TWCMD.C < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-10  |  35.0 KB  |  1,554 lines

  1. /*
  2.     This module handles the Text Window commands
  3. */
  4. #include    "gemdefs.h"
  5. #include    <obdefs.h>
  6. #include    "defs.h"
  7. #include    "keys.h"
  8. #include    "dbase.h"
  9. #include    "deskset2.h"
  10.  
  11. #define        MIN_LEFT    10    /* minimum edit space left    */
  12. #define        MIN_FREE    80L    /* minimum editing space    */
  13. #define        BLTAG        17    /* beginning Local Tag number    */
  14. #define        NUMTAG        200    /* total number of Tags...    */
  15.  
  16. extern    int        txt_handle;        /* TWindow handle    */
  17. extern    GRECT        twork;            /* TWindow work area    */
  18. extern    int        gl_hchar;        /* Text char height    */
  19. extern    int        gl_wchar;        /* Text char width    */
  20. extern    int        *gcurx;            /* Ptr to mouse x    */
  21. extern    int        *gcury;            /* Ptr to mouse y    */
  22. extern    int        msg_buff[];        /* evnt_multi buffer    */
  23. extern    int        gl_apid;        /* ID for appl_write    */
  24. extern    REGION        *gl_region_ptr;        /* current Region Ptr    */
  25. extern    int        force_draw_flag;    /* Force redraw on Prev    */
  26. extern    OBJECT        *ad_menu;        /* OBJECT for menu bar    */
  27. extern    int        BSTATE;            /* Button State...    */
  28. extern    char        *get_edit();
  29.  
  30. extern    char        nuls[];            /* null string (GOG)    */
  31. extern    unsigned char    *setwptr(), *skiptag(), *malloc(), *toeofline();
  32. extern    unsigned char    mapkbd(), getfp(), toupper(), getLch();
  33. extern    int        rewrite_line(), wdw_eol();
  34. extern    unsigned    cb_size;        /* Copy buffer size    */
  35. extern    int        TWhclip;        /* TWindow horiz. clip    */
  36. extern    unsigned char    *prvp1(), *prvp2();
  37.  
  38. static    unsigned char    *last_one;        /* last match pointer    */
  39. static    unsigned char    lkey;            /* last        cmd key    */
  40. static    unsigned char    ckey;            /* current    cmd key    */
  41. static    unsigned char    last_again    = 0;    /* Last Again command    */
  42. static    unsigned char    search_stg [52]    = {0};    /* Search    String    */
  43. static    unsigned char    replace_stg[52] = {0};    /* Replace    String    */
  44. static    char        Ins_Tag        = 0;    /* in Insert Tag mode    */
  45. static    int        inIOm        = 1;    /* Editor Ins/OvW flag    */
  46. static    unsigned char    mrkfbrk;        /* Mark fctN break char */
  47.  
  48. ARTICLE        *TWart_ptr    = (ARTICLE *)0;    /* TW current article    */
  49. char        TWaltered    = 0;        /* TWindow altered flag    */
  50. unsigned char    **upd_ptr    = (char **)0;    /* region ptr tag array    */
  51. int        upd_tags;            /* # of ptrs in array    */
  52. int        mrkfctN        = 0;        /* current Mark functN    */
  53. int        last_tag    = BLTAG;    /* Last used Local Tag    */
  54. int        TWVSLpos    = 0;        /* TW VSlider position    */
  55. int        TWVSLsize    = 1000;        /* TW VSlider size    */
  56.  
  57. /*
  58.     Text Window arrow function handler
  59. */
  60. TW_arrow(action)
  61. int    action;
  62. {
  63.     int    hmove;
  64.  
  65.     if (!TWart_ptr)
  66.         return;
  67.     switch(action) {
  68.     case WA_UPPAGE:  
  69.         pageup_cmd();
  70.         break;
  71.     case WA_DNPAGE: 
  72.         pagedown_cmd();
  73.         break;
  74.     case WA_UPLINE:
  75.         up_cmd(current.row + 1);
  76.         break;
  77.     case WA_DNLINE:
  78.         down_cmd(current.mrow - current.row);
  79.         break;
  80.     case WA_LFPAGE:
  81.         hmove = (TWhclip > current.mcol) ? current.mcol:TWhclip;
  82.         goto toL;
  83.     case WA_RTPAGE:
  84.         hmove = current.mcol;
  85.         goto toR;
  86.     case WA_LFLINE:
  87.         hmove = 1;
  88. toL:        if (TWhclip)
  89.             left_cmd(current.col + hmove);
  90.         break;
  91.     case WA_RTLINE:
  92.         hmove = 1;
  93. toR:        if (current.mcol < wdw_cols)
  94.             TWmoveRight(TWhclip + hmove,hmove);
  95.         break;
  96.     }
  97. }
  98.  
  99. /*
  100.     Text Window mouse button handler
  101. */
  102. TW_button()
  103. {
  104.     int    xcur, ycur, maxcol;
  105.     int    xdiff, ydiff;
  106.     unsigned tagn;
  107.  
  108.     if (!TWart_ptr || !xyinTW(*gcurx,*gcury))
  109.         return(0);
  110.     xcur    = *gcurx - (twork.g_x + gl_wchar);
  111.     if (xcur < 0)
  112.         return(0);
  113.     xcur    /= gl_wchar;
  114.     ycur    = *gcury - twork.g_y;
  115.     ycur    /= gl_hchar;
  116.     if (ydiff = abs(current.row - ycur)) {    /* check move y first    */
  117.         if (current.row > ycur) {
  118.             if (free_start != buf_start)
  119.                 backup(ydiff);
  120.             else    ydiff = 0;
  121.         }
  122.         else {
  123.             if (current_char != buf_end)
  124.                 forup(ydiff);
  125.             else    ydiff = 0;
  126.         }
  127.     }
  128.     maxcol = nchartoEline();        /* ultimate line column    */
  129.     if (ydiff) {                /* if y been moved...    */
  130.         if (maxcol) {
  131.             xdiff    = TWhclip + xcur;
  132.             right_cmd(xdiff > maxcol ? maxcol:xdiff);
  133.         }
  134.         else    nscr(0);
  135.     }
  136.     else
  137.     if (xdiff = abs(current.col - xcur)) {    /* move x only on line    */
  138.         if (current.col > xcur)
  139.             left_cmd(xdiff);
  140.         else    right_cmd(xdiff > maxcol ? maxcol:xdiff);
  141.     }
  142.     if (mrkfctN) {
  143.         if (BSTATE == 2) {
  144.             ckey = mrkfbrk;
  145.             return(1);
  146.         }
  147.     }
  148.     else
  149.     if (!Ins_Tag) {
  150.       if (ptagc(*current_char))        /* if cursor at Pi TAG    */
  151.         PiTag_cmd(*(current_char + 1));
  152.       else
  153.       if (ctagc(*current_char)) {        /* or cursor at Cp TAG    */
  154.         tagn = *(current_char + 1) + 1;
  155. /*        if (tagn >= BLTAG)
  156.             last_tag = tagn;    */
  157.         do_tag(tagn,0);
  158.       }
  159.     }
  160.     return(0);
  161. }
  162.  
  163. /*
  164.     Text Window Top menu handler
  165. */
  166. TW_menu(item)
  167. int    item;
  168. {
  169.     menu_tnormal(ad_menu,TEXT,1);
  170.     switch(item) {
  171.     case SELART:    ckey = ATS;    break;
  172.     case GETXT:    ckey = ATG;    break;
  173.     case DELTXT:    ckey = ATD;    break;
  174.     case BUFTXT:    ckey = ATB;    break;
  175.     case CPYTXT:    ckey = ATC;    break;
  176.     case FORFIND:    ckey = ATF;    break;
  177.     case REVFIND:    ckey = ATV;    break;
  178.     case RPLC:    ckey = ATR;    break;
  179.     case SETMARK:    ckey = ATM;    break;
  180.     case JPMARK:    ckey = ATJ;    break;
  181.     case INSTAG:    ckey = ATT;    break;
  182.     case INSLTAG:    ckey = ATL;    break;
  183.     case DELTAG:    ckey = ATX;    break;
  184.     }
  185.     return(TW_Cmds());
  186. }
  187.  
  188. /*
  189.     Function to process Text window Keyboard commands
  190.     for Cursor/Text/File scrolling and single character
  191.     deletion.
  192. */
  193. TW_Keys()
  194. {
  195.     int    found = true;
  196.  
  197.     if (!TWart_ptr)
  198.         return(0);
  199.     switch(ckey) {
  200.     case bol_char:        bol_cmd();        break;
  201.     case eol_char:        eol_cmd();        break;
  202.     case NextWord_char:    skip_word(1);        break;
  203.     case PrevWord_char:    skip_word(0);        break;
  204.     case left_char:        left_cmd(1);        break;
  205.     case right_char:    right_cmd(1);        break;
  206.     case up_char:        up_cmd(1);        break;
  207.     case down_char:        down_cmd(1);        break;
  208.     case pageup_char:    pageup_cmd();        break;
  209.     case pagedown_char:    pagedown_cmd();        break;
  210.     case bs:        rubout_char();        break;
  211.     case Del_char:        kill_char();        break;
  212.     case bof_char:        bof_cmd();        break;
  213.     case eof_char:        eof_cmd();        break;
  214.     default :        found = false;        break;
  215.     }
  216.     lkey = ckey;
  217.     if (found) flush_kbd();
  218.     return(found);
  219. }
  220.  
  221. /*
  222.     Function to process Text window Alpha commands
  223. */
  224. TW_Cmds()
  225. {
  226.     int    found = true;
  227.  
  228.     if (!TWart_ptr && ckey != ATS)        /* if no article then    */
  229.         return(0);            /* can select it...    */
  230.     switch(ckey) {
  231.     case ATA:
  232.         Again_cmd();            /* from keyboard only    */
  233.         break;
  234.     case ATF: case ATR: case ATV:
  235.         if (FindReplace_cmd(1L,ckey == ATF ? 1:ckey == ATR ? 2:3))
  236.             last_again = ckey;
  237.         else    last_again = 0;
  238.         break;
  239.     case ATJ: case ATM:
  240.         JumpMrk_cmd(ckey == ATM);
  241.         break;
  242.     default :
  243.         if (mrkfctN)
  244.             found = false;
  245.         else
  246.         switch(ckey) {
  247.         case ATD:
  248.             Delete_cmd();    break;
  249.         case ATB:
  250.             Buffer_cmd();    break;
  251.         case ATT:
  252.         case ATL:
  253.             InsTag_cmd(ckey);break;
  254.         case Ins_char:
  255.             inIOm = !inIOm;        /* from keyboard only    */
  256.             TW_state();    break;
  257.         case ATS:
  258.             SelArt_cmd();    break;
  259.         case ATG:
  260.             Get_cmd();    break;
  261.         case ATC:
  262.             Copy_cmd();    break;
  263.         case ATX:
  264.             DelTag_cmd();    break;
  265.         case ATP:
  266.             PiTag_cmd(1);    break;
  267.         default :
  268.             found = false;    break;
  269.         }
  270.         break;
  271.     }
  272.     return(found);
  273. }
  274.  
  275. /*
  276.     Input routine when in Ins/Ovw mode or Block functions
  277.     Returns 0 for Abort or 1 for valid character.
  278. */
  279. Ikey()
  280. {
  281.     int    ret;            /* dummy variable    */
  282.     int    event;            /* which event returned    */
  283.     int    check;            /* check mark mode flag    */
  284.     unsigned kstat;            /* Kbd shift state    */
  285.     unsigned kcode;            /* Kbd return code    */
  286.  
  287.     if (check_TWtop()) while (1) {
  288.       wind_update(check = false);
  289.       event = evnt_multi(MU_MESAG | MU_KEYBD | MU_BUTTON,
  290.         1,1,1,
  291.         0,0,0,0,0,
  292.         0,0,0,0,0,
  293.         msg_buff,0,0,&ret,&ret,&ret,&kstat,&kcode,&ret);
  294.       wind_update(true);
  295.       if (event & MU_MESAG) {
  296.         if (msg_buff[0] == MN_SELECTED) {
  297.           if (msg_buff[3] == TEXT) {    /* check for TW menu    */
  298.             if (!TW_menu(msg_buff[4]) &&
  299.                  TWart_ptr && mrkfctN)
  300.                 check = true;
  301.  
  302.           }
  303.           else    menu_handler(msg_buff[3],msg_buff[4]);
  304.         }
  305.         else    mesag_handle(msg_buff);    /* else go to handler    */
  306.       }
  307.       if (!check_TWtop() && !TWart_ptr)
  308.         return(0);
  309.       if (event & MU_KEYBD) {
  310.         ckey = mapkbd(kstat,kcode);
  311.         if (!TW_Keys() && !TW_Cmds() && TWart_ptr) {
  312.             if (mrkfctN)
  313.                 check = true;
  314.             else
  315.             if (dscck())
  316.                 return(1);
  317.         }
  318.       }
  319.       if (event & MU_BUTTON)
  320.         check = TW_button();
  321.       if (check && (ret = mark_Key()))
  322.         return(ret - 1);
  323.     }
  324.     else    return(0);
  325. }
  326.  
  327. /*
  328.     Routine to scan for valid DeskSet character codes
  329. */
  330. dscck()
  331. {
  332.     return( (ckey >= 0x20 && ckey <= 0xbf)    ||
  333.         (ckey >= 0xf0 && ckey <= 0xfe)    ||
  334.         nocp(ckey) );
  335. }
  336.  
  337. /*
  338.     Routine to check for abort or close command in mark block mode
  339. */
  340. mark_Key()
  341. {
  342.     if (ckey == esc || ckey == ctl_C)
  343.         return(1);
  344.     else
  345.     if (ckey == mrkfbrk)
  346.         return(2);
  347.     else    return(0);
  348. }
  349.  
  350. /*
  351.     Function to move forward in the text buffer.
  352.     Returns updated pointer.
  353. */
  354. unsigned char *mvfwd(ptr)
  355. unsigned char *ptr;
  356. {
  357.     switch(*ptr) {
  358.     case hrt: case srt: case Rf:
  359.         ptr += 3;
  360.         break;
  361.     default:
  362.         ptr = skiptag(ptr);
  363.         if (*ptr != cr)
  364.             break;
  365.     case cr:
  366.         ptr += 2;
  367.         break;
  368.     }
  369.     return(ptr);
  370. }
  371.  
  372. /*
  373.     Function to move backward in the text buffer.
  374.     Returns updated pointer.
  375. */
  376. unsigned char *mvbwd(ptr)
  377. unsigned char *ptr;
  378. {
  379.     if (tagc(*(ptr-2)))
  380.         ptr -= 2;
  381.     else
  382.     if (*(--ptr) == lf) {
  383.         ptr -= 2;
  384.         if (tagc(*(ptr-1)))
  385.             --ptr;
  386.     }
  387.     return(ptr);
  388. }
  389.  
  390. /*
  391.     Function to delete from current char to tag
  392. */
  393. delete_chars(tag)
  394. int    tag;
  395. {
  396.     if (current_char > wdw_ptr[tag])        /* for first buffer  */
  397.         free_start    = wdw_ptr[tag];
  398.     else    current_char    = wdw_ptr[tag];
  399.     if (wdw_ptr[top_line] >= free_start &&        /* if deleting line1 */
  400.         wdw_ptr[top_line] < current_char)
  401.         setwptr(top_line);
  402.     TWrewindow(current_char);
  403.     nsline();
  404.     if (tag == HMRK)
  405.         ckTWsliderV();
  406.     TWaltered = true;
  407. }
  408.  
  409. /*
  410.     Function to check edit buffer limit. Returns true/false
  411. */
  412. Infsp()
  413. {
  414.     if (nofsp()) {
  415.         beep();
  416.         do_alert(BFERR1);
  417.         return(0);
  418.     }
  419.     return(1);
  420. }
  421.  
  422. /*
  423.     Function to change an alpha character to the other case.
  424.     Returns new or old character.
  425. */
  426. static    char unc(c)
  427. char    c;
  428. {
  429.     if (c >= 'a' && c <= 'z') c -= 0x20;
  430.     else
  431.     if (c >= 'A' && c <= 'Z') c += 0x20;
  432.     return(c);
  433. }
  434.  
  435. /*
  436.     Function to forward find a string.
  437.     Returns last search pointer.
  438. */
  439. unsigned char    *f_find(chr, target, count)
  440. unsigned char    chr, *target;
  441. unsigned long    count;
  442. {
  443.     unsigned char    cchr;
  444.     ++count;
  445.     cchr = setp.cign ? unc(chr):chr;
  446.     while (count-- && *target != chr && *target != cchr) ++target;
  447.     return(target);
  448. }
  449.  
  450. /*
  451.     Function to reverse find a string.
  452.     Returns last search pointer.
  453. */
  454. unsigned char    *r_find(chr, target, count)
  455. unsigned char    chr, *target;
  456. unsigned long    count;
  457. {
  458.     unsigned char    cchr;
  459.     ++count;
  460.     cchr = setp.cign ? unc(chr):chr;
  461.     while (count-- && *target != chr && *target != cchr) --target;
  462.     return(target);
  463. }
  464.  
  465. /*
  466.     Function to match a text string in search_stg to the data from ptr.
  467.     Direction denotes forward if true or backward if false.
  468. */
  469. match_string(ptr,direction)
  470. unsigned char    *ptr;
  471. int        direction;
  472. {
  473.     unsigned char    *target, *source;
  474.     int        len;
  475.  
  476.     if (direction) {
  477.       target = &search_stg[0];
  478.       source = ptr;
  479.       while (*target) {
  480.         if (setp.cign) {
  481.         if (toupper(*target) != toupper(*source)) break;
  482.         }
  483.         else if (*target != *source) break;
  484.         ++target; ++source;
  485.         if (source > buf_end) break;
  486.       }
  487.       if (!*target) {
  488.         last_one = source;
  489.         return(true);
  490.       }
  491.       else    return(false);
  492.     }
  493.     else {
  494.       if ((len = strlen(search_stg)) == 1) {
  495.         last_one = ptr;
  496.         return(true);
  497.       }
  498.       target = &search_stg[len-1];
  499.       source = ptr;
  500.       while (target >= search_stg) {
  501.         if (setp.cign) {
  502.         if (toupper(*target) != toupper(*source)) break;
  503.         }
  504.         else if (*target != *source) break;
  505.         --target; --source;
  506.         if (source < buf_start) break;
  507.       }
  508.       if (target == search_stg - 1) {
  509.         last_one = source + 1;
  510.         return(true);
  511.       }
  512.       else    return(false);
  513.     }
  514. }
  515.  
  516. /*
  517.     Function to perform a Cursor-Up command
  518. */
  519. up_cmd(count)
  520. int    count;
  521. {
  522.     if (free_start == buf_start)
  523.         return;
  524.     if (backup(count) == count)
  525.         movetoCcol();
  526.     nscr(0);
  527. }
  528.  
  529. /*
  530.     Function to perform a Cursor-Down command
  531. */
  532. down_cmd(count)
  533. int    count;
  534. {
  535.     if (current_char == buf_end)
  536.         return;
  537.     if (forup(count) == count)
  538.         movetoCcol();
  539.     nscr(0);
  540. }
  541.  
  542. /*
  543.     Function to perform a Cursor-Left command
  544. */
  545. left_cmd(count)
  546. int    count;
  547. {
  548.     unsigned char *ptr = free_start;
  549.     if (ptr == buf_start)
  550.         return;
  551.     while (count-- && ptr > buf_start)
  552.         ptr = mvbwd(ptr);
  553.     rwnscr(ptr,0);
  554. }
  555.  
  556. /*
  557.     Function to perform a Cursor-Right command
  558. */
  559. right_cmd(count)
  560. int    count;
  561. {
  562.     unsigned char *ptr = current_char;
  563.     if (ptr == buf_end)
  564.         return;
  565.     while (count-- && ptr < buf_end)
  566.         ptr = mvfwd(ptr);
  567.     rwnscr(ptr,0);
  568. }
  569.  
  570. /*
  571.     Function to perform a Beginning of Line command by Shift Left
  572. */
  573. bol_cmd()
  574. {
  575.     if (lkey == bol_char) {
  576.         ckey = 0;
  577.         if (wdw_ptr[top_line] == current_char)
  578.             return;
  579.         TWrewindow(wdw_ptr[top_line]);    /* to top of screen instead  */
  580.     }
  581.     else {
  582.         if (wdw_ptr[cur_line()] == current_char)
  583.             return;
  584.         backup(0);            /* beginning of current line */
  585.     }
  586.     nscr(0);
  587. }
  588.  
  589. /*
  590.     Function to perform a End of Line command by Shift Right
  591. */
  592. eol_cmd()
  593. {
  594.     if (lkey == eol_char) {
  595.         ckey = 0;
  596.         if (current.row == current.mrow - 1)
  597.             return;
  598.         TWrewindow(wdw_ptr[bot_line()]);    /* to the last line  */
  599.     }
  600.     else {
  601.         if (lpend(current_char))
  602.             return;
  603.         forup(0);            /* to end of current line    */
  604.     }
  605.     nscr(0);
  606. }
  607.  
  608. /*
  609.     Function to perform a Page-Up command by Shift Up
  610. */
  611. pageup_cmd()
  612. {
  613.     if (current_char == buf_start)
  614.         return;
  615.     TWrewindow(wdw_ptr[top_line]);
  616.     backup(current.mrow - 3);
  617.     nscr(1);
  618. }
  619.  
  620. /*
  621.     Function to perform a Page-Down command by Shift Down
  622. */
  623. pagedown_cmd()
  624. {
  625.     if (current_char == buf_end)
  626.         return;
  627.     TWrewindow(wdw_ptr[bot_line()]);
  628.     forup(3);
  629.     nscr(1);
  630. }
  631.  
  632. /*
  633.     Function to perform a Beginning of File command by Ctl Up
  634. */
  635. bof_cmd()
  636. {
  637.     if (current_char == buf_start)
  638.         return;
  639.     rwnscr(buf_start,1);
  640. }
  641.  
  642. /*
  643.     Function to perform an End of File command by Ctl Down
  644. */
  645. eof_cmd()
  646. {
  647.     if (current_char == buf_end)
  648.         return;
  649.     rwnscr(buf_end,1);
  650. }
  651.  
  652. /*
  653.     Function to find forward or backward the next word
  654.     by Ctl Right or Left
  655. */
  656. skip_word(direction)
  657. int    direction;
  658. {
  659.     unsigned char    *ptr;
  660.     
  661.     if (direction) {            /* either forwards    */
  662.         if (current_char == buf_end)
  663.             return;
  664.         ptr = current_char;
  665.         while ( ptr < buf_end &&    /* skip current word    */
  666.             (calpha(*ptr) || cdigit(*ptr)) )
  667.             ++ptr;
  668.         while ( ptr < buf_end &&    /* skip to next word    */
  669.             !calpha(*ptr) && !cdigit(*ptr) )
  670.             ptr = skiptag(ptr);
  671.     }
  672.     else {                    /* or backwards        */
  673.         if (free_start == buf_start)
  674.             return;
  675.         ptr = free_start;
  676.         while ( ptr > buf_start &&    /* skip current word    */
  677.             !tagc(*(ptr-2)) &&
  678.             (calpha(*(ptr-1)) || cdigit(*(ptr-1))) )
  679.             --ptr;
  680.         while ( ptr > buf_start ) {    /* scan for prev word    */
  681.             if (tagc(*(ptr-2)))
  682.                 ptr -= 2;
  683.             else
  684.             if (!calpha(*(ptr-1)) && !cdigit(*(ptr-1)))
  685.                 --ptr;
  686.             else    break;
  687.         }
  688.         if (ptr > buf_start) --ptr;    /* set to end of word    */
  689.     }
  690.     rwnscr(ptr,0);
  691. }
  692.  
  693. /*
  694.     Function to delete a character at cursor
  695. */
  696. kill_char()
  697. {
  698.     int        nline;
  699.     unsigned char    *ptr = current_char;
  700.     if (ptr < buf_end) {
  701.         if (ctagc(*ptr))
  702.             return(right_cmd(1));
  703.         else
  704.         if (nline = allend(*ptr))
  705.             ptr += 3;
  706.         else
  707.         if (ptagc(*ptr) ||
  708.            (nline = (*(++ptr) == cr)))
  709.             ptr += 2;
  710.         if (ptr <= buf_end) {
  711.             wdw_ptr[TMP1] = ptr;
  712.             delete_chars(TMP1);
  713.             if (nline) ckTWsliderV();
  714.         }
  715.     }
  716. }
  717.  
  718. /*
  719.     Function to delete a character prior to the cursor
  720. */
  721. rubout_char()
  722. {
  723.     int        nline = 0;
  724.     unsigned char    *ptr = free_start;
  725.     if (ptr > buf_start) {
  726.         if (ctagc(*(ptr-2)))
  727.             return(left_cmd(1));
  728.         else
  729.         if (ptagc(*(ptr-2)))
  730.             ptr -= 2;
  731.         else
  732.         if (nline = (*(--ptr) == lf)) {
  733.             ptr -= 2;
  734.             if (tagc(*(ptr-1)))
  735.                 ++ptr;
  736.         }
  737.         if (ptr >= buf_start) {
  738.             setwptr(TMP1);
  739.             TWrewindow(ptr);
  740.             delete_chars(TMP1);
  741.             if (nline) ckTWsliderV();
  742.         }
  743.     }
  744. }
  745.  
  746. /*
  747.     Command to perform global search (forward or backward)
  748.     then optionally replace with user string after match.
  749.     Can be repeated by user specified number of times.
  750. */
  751. FindReplace_cmd(repeat,direction)
  752. unsigned long    repeat;
  753. int        direction;
  754. {
  755.     OBJECT        *dialog;
  756.     int        bxobj, stobj, exobj, abobj, ulobj;
  757.     int        i, status, mod, slen, rlen;
  758.     unsigned long    begcnt;
  759.     unsigned char    *ptr;
  760.  
  761.     mod = abs(direction);
  762.     if (direction < 0) goto FR_ag;            /* detect Again mode */
  763.     if (mod == 1)                    /* for 1, Find         */
  764.       bxobj = FIND, stobj = FFST,
  765.       ulobj = FDUL, abobj = FDNOK;
  766.     else
  767.     if (mod == 2)                    /* for 2, Replace    */
  768.       bxobj = RPLACE, stobj = RFST,
  769.       ulobj = RPUL,   abobj = RPNOK;
  770.     else                        /* for 3, Rev. find  */
  771.       bxobj = RFIND, stobj = RVST,
  772.       ulobj = RVFUL, abobj = RVFNOK;
  773.  
  774.     rsrc_gaddr(0,bxobj,&dialog);
  775.     dialog[ulobj].ob_state = setp.cign ? SELECTED:NORMAL;
  776.     set_tedit(dialog,stobj,search_stg);
  777.     if (mod == 2)                    /* for Replace only  */
  778.         set_tedit(dialog,RRST,replace_stg);
  779.  
  780.     exobj = execform(dialog,0);
  781.     dialog[exobj].ob_state = NORMAL;
  782.     if (exobj == abobj)
  783.         return(false);
  784.     BWredraw();                    /* redraw T/P Window */
  785.     setp.cign = (dialog[ulobj].ob_state == SELECTED);
  786.     strcpy(search_stg,get_edit(dialog,stobj));
  787.     if (mod == 2) {                    /* for Replace only  */
  788.         strcpy(replace_stg,get_edit(dialog,RRST));
  789.         if (exobj == RPALL)
  790.             repeat = -1L;
  791.     }
  792.  
  793. FR_ag:    if (!*search_stg)
  794.         return(false);                /* nothing to find   */
  795.     slen = strlen(search_stg);            /* use search length */
  796.     last_one = current_char;
  797.     ptr = mod < 3 ? current_char:free_start-1;
  798.     status = true;
  799.     begcnt = repeat - 1;
  800.  
  801.     while (repeat--) {
  802.       if (mod < 3) while (1) {            /* forward search... */
  803.         if ( ptr >= buf_end ||
  804.         (ptr = f_find(search_stg[0],ptr,(long)(buf_end - ptr) + 1))
  805.             >= buf_end ) {
  806. FR_nf:        if (repeat == begcnt)
  807.             do_alert(FRNFD);
  808.         status = false;
  809.         goto FR_ex;
  810.         }
  811.         else if (match_string(ptr,1)) {
  812.         if (mod == 1) {            /* for fwd search only done  */
  813.             if (repeat) ++ptr; break;
  814.         }                /* else do string replace... */
  815.         TWrewindow(ptr);        /* string is at current char */
  816.         rlen = strlen(replace_stg);
  817.         if (free_start + rlen >= current_char + slen - MIN_LEFT) {
  818.             do_alert(FRBFE);
  819.             status = false;
  820.             goto FR_ex;
  821.         }
  822.         i = cur_line();
  823.         if (wdw_ptr[i] == current_char)
  824.             wdw_ptr[i] = free_start;
  825.         current_char += slen;            /* delete old one... */
  826.         strcpy(free_start,replace_stg);
  827.         free_start += rlen;            /* & insert new one. */
  828.         ptr = current_char;
  829.         TWaltered = true;            /* mark text altered */
  830.         break;
  831.         }
  832.         else ++ptr;
  833.       }
  834.       else while (1) {                /* reverse search... */
  835.         if (ptr <= buf_start ||
  836.         (ptr = r_find(search_stg[slen-1],ptr,(long)(ptr - buf_start)))
  837.             <= buf_start )
  838.             goto FR_nf;
  839.         else if (match_string(ptr,0)) {
  840.         if (repeat) --ptr; break;
  841.         }
  842.         else --ptr;
  843.       }
  844.     }
  845. FR_ex:    TWrewindow(last_one);
  846.     if (mod == 1 || mod == 3)        /* for Forward/Reverse Find  */
  847.         Creview(0);
  848.     else {                    /* else for Replace only...  */
  849.         for (i = bot_line();i > top_line;--i)
  850.             if (wdw_ptr[i]) break;        /* ensure new screen */
  851.         Creview(last_one < wdw_ptr[i] ? 3:2);
  852.     }
  853.     cursor();
  854.     return(status);
  855. }
  856.  
  857. /*
  858.     Function to repeat the last Search/Replace command
  859. */
  860. Again_cmd()
  861. {
  862.     int    mod;
  863.  
  864.     if (!last_again)
  865.         return;
  866.     if (last_again == ATF) mod = -1;
  867.     else
  868.     if (last_again == ATR) mod = -2;
  869.     else
  870.     if (last_again == ATV) mod = -3;
  871.     if (!FindReplace_cmd(1L,mod))
  872.         last_again = 0;
  873. }
  874.  
  875. /*
  876.     Function to set either Insert/Overwrite mode state
  877.     or current Mark command on Info line.
  878. */
  879. TW_state()
  880. {
  881.     int    msgno;
  882.  
  883.     if (mrkfctN)
  884.         msgno = mrkfctN;
  885.     else
  886.     if (inIOm) {
  887.         msgno = INMS;    wdw_crsnm();
  888.     }
  889.     else {
  890.         msgno = OVMS;    wdw_crsbx();
  891.     }
  892.     TW_info(msgno);
  893. }
  894.  
  895. /*
  896.     Editor handler
  897. */
  898. Editor()
  899. {
  900.     while (1) {
  901.       if (!Ikey())                    /* time to quit mode */
  902.         return;
  903.       else {                    /* or stay in mode.. */
  904.         if ((ckey == ' '        &&        /* check 2 spaces    */
  905.         getLch(free_start-1) == ' ')
  906.             ||
  907.         (ckey != ' '        &&        /* check flash pos.  */
  908.         !nocp(ckey)        &&
  909.         getfp(ckey) == 0xff)) {
  910.         beep(); continue;            /* error skip input  */
  911.         }
  912.         if (!Infsp()) continue;            /* no room continue  */
  913.         if (ckey == cr) ckey = hrt;            /* swap cr to hrt... */
  914.         if (allend(ckey)) {                /* user line endings */
  915.         TWclipdraw(wdw_eol,ckey);        /* update wdow line  */
  916.         *free_start++ = ckey;            /* insert hrt/cr/lf  */
  917.         ckcrlf();
  918.         if (wdw_ptr[cur_line()] == current_char)
  919.             wdw_ptr[cur_line()] = free_start - 3;
  920.         nsline();
  921.         }
  922.         else {                    /* or user reg input */
  923.         if (    inIOm            ||    /* if in Insert mode */
  924.             tagc(*current_char)    ||    /* or cursor at TAG  */
  925.             allend(*current_char)    ||    /* or at line ending */
  926.             current_char >= buf_end ) {    /* or at end buffer  */
  927.             *(--current_char) = ckey;    /* do Insert mode... */
  928.             if (!TWhclip && !current.col)
  929.                 setwptr(cur_line());
  930.         }
  931.         else    *current_char = ckey;        /* else do Overwrite */
  932.         wdw_ptr[HMRK] = skiptag(current_char);
  933.         if (*wdw_ptr[HMRK] == cr)
  934.             wdw_ptr[HMRK] += 2;
  935.         cursor();
  936.         TWclipdraw(rewrite_line,0);        /* now refresh line  */
  937.         TWrewindow(wdw_ptr[HMRK]);
  938.         cursor();
  939.         }
  940.         TWaltered = true;                /* set file altered  */
  941.       }                        /* end of stayinmode */
  942.     }                        /* end of while (1)  */
  943. }
  944.  
  945. /*
  946.     Command to jump and set cursor to an user specified marker.
  947. */
  948. JumpMrk_cmd(which)
  949. int    which;
  950. {
  951.     OBJECT    *dialog;
  952.     int    bxobj, exobj, abobj, bn;
  953.  
  954.     if (which)                /* for Set Marker cmd    */
  955.       bxobj = SETAG, abobj = STGNOK;
  956.     else                    /* for Jump Marker cmd    */
  957.       bxobj = JPTAG, abobj = JTGNOK;
  958.     rsrc_gaddr(0,bxobj,&dialog);
  959.     exobj = execform(dialog,0);
  960.     dialog[exobj].ob_state = NORMAL;
  961.     if (exobj == abobj)
  962.         return;
  963.     BWredraw();                /* redraw T/P Windows    */
  964.     switch(exobj) {
  965.     case STGA:/* case JTGA: same */
  966.         bn = mrk_base;
  967.         break;
  968.     case STGB:/* case JTGB: same */
  969.         bn = mrk_base + 1;
  970.         break;
  971.     case STGC:/* case JTGC: same */
  972.         bn = mrk_base + 2;
  973.         break;
  974.     case STGD:/* case JTGD: same */
  975.         bn = mrk_base + 3;
  976.         break;
  977.     }
  978.     if (which)
  979.         setwptr(bn);
  980.     else
  981.     if (current_char != wdw_ptr[bn]) {
  982.         TWrewindow(wdw_ptr[bn]);
  983.         nscr(0);
  984.     }
  985. }
  986.  
  987. /*
  988.     Routine to (un)check a mark function in Text menu
  989.     and (en)disable inappropriate functions in mark mode.
  990. */
  991. mrkfcheck(mode)
  992. int    mode;
  993. {
  994.     int    markf, disf1, disf2, disf3;
  995.  
  996.     switch(mrkfbrk) {
  997.     case ATD:    markf = DELTXT;
  998.             disf1 = BUFTXT;
  999.             disf2 = INSTAG;
  1000.             disf3 = INSLTAG;
  1001.             break;
  1002.     case ATB:    markf = BUFTXT;
  1003.             disf1 = DELTXT;
  1004.             disf2 = INSTAG;
  1005.             disf3 = INSLTAG;
  1006.             break;
  1007.     case ATT:    markf = INSTAG;
  1008.             disf1 = DELTXT;
  1009.             disf2 = BUFTXT;
  1010.             disf3 = INSLTAG;
  1011.             break;
  1012.     case ATL:    markf = INSLTAG;
  1013.             disf1 = DELTXT;
  1014.             disf2 = BUFTXT;
  1015.             disf3 = INSTAG;
  1016.             break;
  1017.     }
  1018.     menu_icheck (ad_menu,markf,mode);
  1019.     menu_ienable(ad_menu,disf1,!mode);
  1020.     menu_ienable(ad_menu,disf2,!mode);
  1021.     menu_ienable(ad_menu,disf3,!mode);
  1022.     menu_ienable(ad_menu,SELART,!mode);
  1023.     menu_ienable(ad_menu,GETXT,!mode);
  1024.     menu_ienable(ad_menu,CPYTXT,!mode);
  1025.     menu_ienable(ad_menu,DELTAG,!mode);
  1026. }
  1027.  
  1028. /*
  1029.     Function to mark a block
  1030. */
  1031. mark_blk(fctN,fbrk)
  1032. int    fctN;
  1033. char    fbrk;
  1034. {
  1035.     mrkfctN = fctN;
  1036.     mrkfbrk = fbrk;
  1037.     mrkfcheck(true);
  1038.     TW_state();
  1039.     cursor();
  1040.     setwptr(HMRK);
  1041.     wdw_mark();
  1042.     fctN = Ikey();
  1043.     mrkfcheck(false);
  1044.     mrkfctN = false;
  1045.     return(fctN);
  1046. }
  1047.  
  1048. /*
  1049.     Function to find matching start or end Tag
  1050. */
  1051. unsigned char    *match_tag(fdir,tagn,sptr,eptr)
  1052. int        fdir;
  1053. unsigned char    tagn, *sptr, *eptr;
  1054. {
  1055.     if (fdir) {                /* test find ETAG    */
  1056.       if (sptr >= eptr)
  1057.         goto quit;
  1058.       while (sptr < eptr) {            /* scan forward...    */
  1059.         if (*sptr == ETAG && *(sptr+1) == tagn)
  1060.             return(sptr);
  1061.         sptr = mvfwd(sptr);
  1062.       }
  1063.     }
  1064.     else {                    /* or    find STAG    */
  1065.       if (sptr == eptr)
  1066.         goto quit;
  1067.       while (sptr > eptr) {            /* scan backward...    */
  1068.         sptr = mvbwd(sptr);
  1069.         if (*sptr == STAG && *(sptr+1) == tagn)
  1070.             return(sptr);
  1071.       }
  1072.     }
  1073. quit:    return((char *)0);            /* search fails...    */
  1074. }
  1075.  
  1076. /*
  1077.     Function to check for unmatched start and end Tag
  1078.     within a block delimited by HMRK(start) and TMP1(end)
  1079. */
  1080. UnmatchTag()
  1081. {
  1082.     unsigned char    *sp, *ep;
  1083.     int        err = 0;
  1084.  
  1085.     if (wdw_ptr[HMRK] > current_char)    /* if start tag    ptr    */
  1086.     {                    /* in 2nd partition    */
  1087.         wdw_ptr[TMP1] = wdw_ptr[HMRK];
  1088.         setwptr(HMRK);            /* swap begin/end ptr    */
  1089.     }
  1090.     else    setwptr(TMP1);            /* else set end tag ptr    */
  1091.     TWrewindow(wdw_ptr[HMRK]);        /* to begin tag mark to    */
  1092.     for (    sp = current_char,        /* check unclosed STAG    */
  1093.         ep = wdw_ptr[TMP1];
  1094.         !err && sp < ep;
  1095.         sp = mvfwd(sp)    )
  1096.       if (*sp == STAG &&                /* if hit STAG    */
  1097.         !match_tag(1,*(sp+1),sp+2,ep))        /* find   ETAG    */
  1098.       {    do_alert(TAGERR2);        /* no match error quit    */
  1099.         err = 1;    }
  1100.     TWrewindow(wdw_ptr[TMP1]);        /* to end tag mark to    */
  1101.     if (!err)
  1102.     for (    sp = free_start,        /* check unclosed ETAG    */
  1103.         ep = wdw_ptr[HMRK];
  1104.         !err && sp > ep;  ) {
  1105.       sp = mvbwd(sp);
  1106.       if (*sp == ETAG &&                /* if hit ETAG    */
  1107.         !match_tag(0,*(sp+1),sp,ep))        /* find   STAG    */
  1108.       {    do_alert(TAGERR2);        /* no match error quit    */
  1109.         err = 1;    }
  1110.     }
  1111.     return(err);
  1112. }
  1113.  
  1114. /*
  1115.     Command to perform block deletion from cursor
  1116. */
  1117. Delete_cmd()
  1118. {
  1119.     int    no_fit;
  1120.     
  1121.     if (!mark_blk(DMENU,ATD)) {
  1122.         if (!check_TWtop())
  1123.             return;
  1124.         else    goto del_q;
  1125.     }
  1126.     if (!wdw_ptr[HMRK] || wdw_ptr[HMRK] == current_char)
  1127.         goto del_q;
  1128.     if (wdw_ptr[HMRK] < current_char) {    /* in 1st partition    */
  1129. /*?*/        if (*current_char == cr)
  1130.             TWrewindow(current_char + 2);
  1131.         else
  1132.         if (*current_char == srt)
  1133.             TWrewindow(current_char + 3);
  1134.     }
  1135.     else
  1136.     if (wdw_ptr[HMRK] > current_char) {    /* in 2nd partition    */
  1137. /*?*/        if (*wdw_ptr[HMRK] == cr)
  1138.             wdw_ptr[HMRK] += 2;
  1139.         else
  1140.         if (*wdw_ptr[HMRK] == srt)
  1141.             wdw_ptr[HMRK] += 3;
  1142.     }
  1143.     if (UnmatchTag())            /* check unmatched tag    */
  1144.         goto del_q;
  1145.     no_fit = cb_bufin(wdw_ptr[HMRK],(long)(free_start - wdw_ptr[HMRK]));
  1146.     if (no_fit) {        /* if deleted data cannot be saved...    */
  1147.         if (do_alert(DELOK) == 2)    /* check with user...    */
  1148. del_q:            nscr(3);
  1149.         else    delete_chars(HMRK);    /* ok..do the deletion    */
  1150.     }
  1151.     else    delete_chars(HMRK);        /* else do the deletion    */
  1152.     TW_state();
  1153. }
  1154.  
  1155. /*
  1156.     Command to perform data buffering by saving it into the copy
  1157.     buffer for later use... like block move...
  1158. */
  1159. Buffer_cmd()
  1160. {
  1161.     if (!mark_blk(BMENU,ATB)) {
  1162.         if (!check_TWtop())
  1163.             return;
  1164.         else    goto buf_q;
  1165.     }
  1166.     if (!wdw_ptr[HMRK] || wdw_ptr[HMRK] == current_char)
  1167.         goto buf_q;
  1168.     if (UnmatchTag())            /* check unmatched tag    */
  1169.         goto buf_q;
  1170.     if (cb_bufin(wdw_ptr[HMRK],(long)(free_start - wdw_ptr[HMRK])))
  1171.         do_alert(TBMS);
  1172. buf_q:    nscr(3);
  1173.     TW_state();
  1174. }
  1175.     
  1176. /*
  1177.     Command to perform Tag insertion
  1178.     mode :    ATT -- Global
  1179.         ATL -- Local
  1180. */
  1181. InsTag_cmd(mode)
  1182. unsigned char    mode;
  1183. {
  1184.     unsigned    tagnum, Local;
  1185.  
  1186.     Ins_Tag = true;
  1187.     Local    = (mode == ATL);
  1188.     if (!mark_blk(Local ? ILTAG:IGTAG,mode)) {
  1189.         if (!check_TWtop())
  1190.             return(Ins_Tag = false);
  1191.         else    goto inT_q;
  1192.     }
  1193.     if (!wdw_ptr[HMRK] || wdw_ptr[HMRK] == current_char)
  1194.         goto inT_q;
  1195.     if (Infsp() && !UnmatchTag()) {        /* check insert space    */
  1196.                         /* and unmatched tag    */
  1197.         if (Local)            /* if Local Tag mode    */
  1198.             tagnum = last_tag;    /* use last tag number    */
  1199.         else    tagnum = 1;
  1200.         tagnum = do_tag(tagnum,1);    /* call Tag dialog box    */
  1201.         BWredraw();            /* redraw T/P Windows    */
  1202.         if (tagnum) {            /* valid tag selected ?    */
  1203.           if (Local) {            /* if Local Tag mode    */
  1204.             if (last_tag == tagnum &&
  1205.               ++last_tag > NUMTAG)
  1206.                 last_tag = BLTAG;
  1207. /*            last_tag = tagnum;    ** update last tag #    */
  1208.           }
  1209.           --tagnum;            /* tag start from 0    */
  1210.           TWrewindow(wdw_ptr[HMRK]);    /* to begin tag mark    */
  1211.           if (wdw_ptr[cur_line()] == current_char)
  1212.             wdw_ptr[cur_line()] = free_start;
  1213.           *free_start++ = STAG;        /* insert STAG+tagnum    */
  1214.           *free_start++ = (char)tagnum;
  1215.           TWrewindow(wdw_ptr[TMP1]);    /* to end tag mark    */
  1216.           *free_start++ = ETAG;        /* insert ETAG+tagnum    */
  1217.           *free_start++ = (char)tagnum;
  1218.           TWrewindow(current_char);
  1219.           TWaltered = true;
  1220.         }
  1221.     }
  1222. inT_q:    nscr(3);
  1223.     Ins_Tag = false;
  1224.     TW_state();
  1225. }
  1226.  
  1227. /*
  1228.     Command to perform Tag deletion
  1229. */
  1230. DelTag_cmd()
  1231. {
  1232.     int        fdir;            /* 1: fwd, 0: bwd mode    */
  1233.     unsigned char    *sp, *ep, tagn;
  1234.  
  1235.     if (!ctagc(*current_char))        /* if no TAG do exit...    */
  1236.         return;
  1237.     tagn    = *(current_char + 1);
  1238.     fdir    = (*current_char == STAG);    /* check search mode    */
  1239.     if (fdir) {                /* HMRK:start, TMP1:end    */
  1240.         setwptr(HMRK);            /* set HMRK find TMP1    */
  1241.         sp = current_char + 2;
  1242.         ep = buf_end;
  1243.     }
  1244.     else {
  1245.         setwptr(TMP1);            /* set TMP1 find HMRK    */
  1246.         sp = free_start;
  1247.         ep = buf_start;
  1248.     }
  1249.     if (!(ep = match_tag(fdir,tagn,sp,ep)))    /* find S or E TAG    */
  1250.         return(do_alert(TAGERR1));    /* no match error quit    */
  1251.     if (do_alert(KILLTAG) == 2)        /* recheck with user...    */
  1252.         return;                /* (s)he aborts, quit..    */
  1253.     wdw_ptr[fdir ? TMP1:HMRK] = ep;        /* save S or E    tag ptr    */
  1254.     wdw_ptr[TMP4] = current_char + 2;    /* save after    tag ptr    */
  1255.     TWrewindow(wdw_ptr[HMRK]);        /* to begin tag mark    */
  1256.     current_char += 2;
  1257.     TWrewindow(wdw_ptr[TMP1]);        /* to end   tag mark    */
  1258.     current_char += 2;
  1259.     TWrewindow(wdw_ptr[TMP4]);        /* to after tag mark    */
  1260.     nscr(3);
  1261.     TWaltered = true;
  1262. }
  1263.  
  1264. /*
  1265.     Command to perform data (created by the Delete or Buffer command)
  1266.     copy by restoring it from the copy buffer and inserting it at
  1267.     present cursor position.
  1268. */
  1269. Copy_cmd()
  1270. {
  1271.     unsigned char    *optr;
  1272.     unsigned long    fsp;
  1273.     
  1274.     if (!cb_size) return;
  1275.     TW_info(CMENU);
  1276.     fsp = free_space();
  1277.     if (fsp <= MIN_FREE || (unsigned long)cb_size > fsp - MIN_LEFT)
  1278.         do_alert(CPBFE);
  1279.     else {
  1280.         cb_bufout(optr = free_start);
  1281.         free_start += cb_size;
  1282.         TWrewindow(optr);
  1283.         nsline();
  1284.         ckTWsliderV();
  1285.         TWaltered = true;
  1286.     }
  1287.     TW_state();
  1288. }
  1289.  
  1290. /*
  1291.     Command to read in another file into the present edited article
  1292. */
  1293. Get_cmd()
  1294. {
  1295.     char    fname[100];
  1296.  
  1297.     TW_info(GMENU);
  1298.     if (gdosfname(fname,4,1)) {
  1299.         switch(read_file(fname)) {
  1300.         case -1:
  1301.             setnfd(fname,2);
  1302.             break;
  1303.         case 2:
  1304.             do_alert(BFERR2);
  1305.             break;
  1306.         case 1:
  1307.             do_alert(BFERR3);
  1308.         case 0:
  1309.             TWaltered = true;    /* set file altered  */
  1310.             break;
  1311.         }
  1312.         nsline();
  1313.         ckTWsliderV();
  1314.     }
  1315.     TW_state();
  1316. }
  1317.  
  1318. /*
  1319.     Command to select article from dialog box
  1320. */
  1321. extern    ARTICLE    *do_artobj();
  1322. SelArt_cmd()
  1323. {
  1324.     ARTICLE    *art_ptr;
  1325.  
  1326.     if (!(art_ptr = do_artobj()))        /* to selection dialog box  */
  1327.         return;
  1328.     if (TWart_ptr) saveTWptrs();        /* update old article ptrs  */
  1329.     TWart_ptr = art_ptr;
  1330.     setTWArt();                /* set current TW article   */
  1331.     TWrewindow(buf_start);            /* to beginning of article  */
  1332.     TWslider_chk();                /* reset TW H/Vsliders      */
  1333. }
  1334.  
  1335. /*
  1336.     Function to set article from region pointer
  1337. */
  1338. setTWArticle(rptr,txtptr)
  1339. REGION    *rptr;
  1340. char    *txtptr;
  1341. {
  1342.     TWart_ptr = rptr->artptr;        /* get article from region  */
  1343.     if (!TWart_ptr)                /* if no article associated */
  1344.         return(TW_name(nuls));        /* with region return...    */
  1345.     setTWArt();                /* set current TW article   */
  1346.     if (!txtptr)
  1347.         TWrewindow(rptr->txtstart);    /* to beginning of region   */
  1348.     else    TWrewindow(txtptr);
  1349.     TWslider_chk();                /* reset TW H/Vsliders      */
  1350. }
  1351.  
  1352. /*
  1353.     Function to set article from current TW article pointer
  1354. */
  1355. setTWArt()
  1356. {
  1357.     REGION    *rptr, *tptr;
  1358.     char    **bptr;
  1359.     int    i;
  1360.  
  1361.     get_abuffvars(TWart_ptr);        /* get article buffer ptrs  */
  1362.     rptr = TWart_ptr->regptr;        /* get first region        */
  1363.     if (rptr && (rptr = rptr->alink)) {
  1364.         upd_tags = 1;
  1365.         tptr = rptr;
  1366.         while (tptr = tptr->alink)
  1367.             ++upd_tags;
  1368.         if (upd_ptr = (char **)malloc(4 * upd_tags)) {
  1369.             bptr = upd_ptr;
  1370.             do *(bptr++) = rptr->txtstart;
  1371.             while (rptr = rptr->alink);
  1372.         }
  1373.     }
  1374.     for (i = 0;i < 4;) setwptr(i++);    /* reset all text markers   */
  1375.     TWaltered = 0;                /* reset buffer dirty flag  */
  1376.     TW_name(TWart_ptr->filename);        /* set TWname to art. name  */
  1377.     inIOm = 1;                /* start in Insert mode     */
  1378.     TW_state();
  1379. }
  1380.  
  1381. saveTWptrs()
  1382. {
  1383.     ARTICLE    *art_ptr;
  1384.     REGION    *rptr;
  1385.     char    **bptr;
  1386.  
  1387.     TWrewindow(buf_end);            /* to end of article    */
  1388.     put_abuffvars(art_ptr = TWart_ptr);    /* save art. buf. ptrs    */
  1389.     TWart_ptr = (ARTICLE *)0;        /* null TW article ptr    */
  1390.     TW_name(nuls);                /* clear window name    */
  1391.     TW_info(-1);
  1392.     if (TWaltered) {
  1393.         art_ptr->dirty = 1;        /* Set modified flag    */
  1394.         if (rptr = art_ptr->regptr) {
  1395.           if ((rptr = rptr->alink) && upd_ptr) {
  1396.             bptr = upd_ptr;
  1397.             do rptr->txtstart = *(bptr++);
  1398.             while (rptr = rptr->alink);
  1399.           }
  1400.           gl_region_ptr = art_ptr->regptr;
  1401.           recalc_rtext();
  1402.           force_draw_flag = 1;        /* Force redraw on Prev    */
  1403.         }
  1404.     }
  1405.     if (upd_ptr) {
  1406.         free(upd_ptr);
  1407.         upd_ptr = (char **)0;
  1408.     }
  1409. }
  1410.  
  1411. TWslider_chk()
  1412. {
  1413.     TWsliderH();                /* set Hslider position    */
  1414.     wind_set(txt_handle,WF_HSLSIZE,        /* set Hslider size    */
  1415.         scale_iv(1000,current.mcol,wdw_cols),0,0,0);
  1416.     TWsliderV();                /* set Vslider position    */
  1417. }
  1418.  
  1419. TWsliderV()
  1420. {
  1421.     if (TWart_ptr) currentVpos();
  1422.                         /* set Vslider position    */
  1423.     wind_set(txt_handle,WF_VSLIDE,TWVSLpos,0,0,0);
  1424.                         /* set Vslider size    */
  1425.     wind_set(txt_handle,WF_VSLSIZE,TWVSLsize,0,0,0);
  1426. }
  1427.  
  1428. TWsliderH()
  1429. {
  1430.     wind_set(txt_handle,WF_HSLIDE,
  1431.         scale_iv(1000,TWhclip,wdw_cols - current.mcol),0,0,0); 
  1432. }
  1433.  
  1434. TWvslide(position)
  1435. int    position;
  1436. {
  1437.     char    *txtptr;
  1438.     long    fsize;
  1439.  
  1440.     if (!TWart_ptr || position == TWVSLpos)
  1441.         return;
  1442.     if (position <= 1)
  1443.         bof_cmd();
  1444.     else
  1445.     if ((position + TWVSLsize) >= 1000)
  1446.         eof_cmd();
  1447.     else {
  1448.         fsize    = (long)(free_start - buf_start) +
  1449.               (long)(buf_end - current_char);
  1450.         txtptr    = buf_start + (((long)position * fsize) / 1000L);
  1451.         if (txtptr < free_start) {    /* if in 1st partition    */
  1452.           txtptr = prvp1(txtptr);
  1453.           if (*txtptr == cr)
  1454.             txtptr += 2;
  1455.         }
  1456.         if (txtptr >= free_start) {    /* if in 2nd partition    */
  1457.           txtptr = current_char + (long)(txtptr - free_start);
  1458.           if (txtptr == current_char)
  1459.             return;
  1460.           txtptr = prvp2(txtptr);
  1461.           if (*txtptr == cr)
  1462.             txtptr += 2;
  1463.           if (txtptr > buf_end)
  1464.             txtptr = buf_end;
  1465.         }
  1466.         TWrewindow(txtptr);
  1467.         backup(0);            /* to beginning of line    */
  1468.         nscr(1);
  1469.     }
  1470. }
  1471.  
  1472. TWhslide(position)
  1473. int    position;
  1474. {
  1475.     int    xdiff;
  1476.     int    curspos;
  1477.  
  1478.     if (!TWart_ptr)
  1479.         return;
  1480.     position = scale_iv(position,wdw_cols - current.mcol,1000);
  1481.     if (abs(TWhclip - position)) {
  1482.       curspos = TWhclip + current.col;
  1483.       xdiff      = abs(curspos - position);
  1484.       if (TWhclip > position)
  1485.         left_cmd(xdiff);
  1486.       else {
  1487.         if (position <= curspos)
  1488.             TWsetHclip(position);
  1489.         else    TWmoveRight(position,xdiff);
  1490.       }
  1491.     }
  1492. }
  1493.  
  1494. TWsetHclip(position)
  1495. int    position;
  1496. {
  1497.     TWhclip = position;
  1498.     TWsliderH();
  1499.     nscr(3);
  1500. }
  1501.  
  1502. TWmoveRight(position,moveR)
  1503. int    position, moveR;
  1504. {
  1505.     int    xdiff;
  1506.  
  1507.     if ((TWhclip + current.mcol) >= wdw_cols)
  1508.         return;
  1509.     xdiff = nchartoEline();            /* # of chars to eoline */
  1510.     if (xdiff > 0)                /* move cursor first    */
  1511.         right_cmd(xdiff > moveR ? moveR:xdiff);
  1512.     if (position != TWhclip) {        /* if hclip not correct    */
  1513.       if (position > (wdw_cols - current.mcol))
  1514.         position = wdw_cols - current.mcol;
  1515.       if (position > (TWhclip + current.col))
  1516.         position = TWhclip + current.col;
  1517.       TWsetHclip(position);            /* force rescreen...    */
  1518.     }
  1519. }
  1520.  
  1521. currentVpos()
  1522. {
  1523.     long    fsize, temp;
  1524.  
  1525.     temp    = (long)(free_start - buf_start);
  1526.     fsize    = temp + (long)(buf_end - current_char);
  1527.     TWVSLpos = (int)((1000L * temp) / fsize);
  1528.  
  1529.     temp    = (long)current.mrow * (long)current.mcol;
  1530.     if (temp > fsize)
  1531.         temp = fsize;
  1532.     TWVSLsize = (int)((1000L * temp) / fsize);
  1533. }
  1534.  
  1535. PiTag_cmd(fpos)
  1536. int    fpos;
  1537. {
  1538.     if (!pi_tag(&fpos))
  1539.         return;
  1540.     if (ptagc(*current_char))        /* if cursor at Pi TAG    */
  1541.         *(current_char+1) = (char)fpos;    /* overwrite old one    */
  1542.     else
  1543.     if (Infsp()) {                /* check insert space    */
  1544.         if (wdw_ptr[cur_line()] == current_char)
  1545.             wdw_ptr[cur_line()] = free_start;
  1546.         *free_start++ = PTAG;        /* insert PTAG + fpos    */
  1547.         *free_start++ = (char)fpos;
  1548.         TWrewindow(current_char);
  1549.     }
  1550.     else    return;
  1551.     TWaltered = true;
  1552.     nscr(3);
  1553. }
  1554.